package com.east.sng.controller;

import com.east.sng.entity.param.SyslogParam;
import com.east.sng.entity.result.UserFind;
import com.east.sng.service.RoleService;
import com.east.sng.service.SyslogService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Arrays;
import java.util.Date;
import java.util.Set;

/**
 * @author east
 * @date: 2020/12/28
 * @Description:
 **/
@ControllerAdvice
public class GlobalExceptionHandle {
    @Autowired
    private SyslogService syslogService;
    @Autowired
    private RoleService roleService;

    /**
     * 验证异常处理
     * @param attr
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(ValidationException.class)
    public String validationHandle(RedirectAttributes attr,HttpServletRequest request, ValidationException ex) {
        if(ex instanceof ConstraintViolationException){
            ConstraintViolationException exs = (ConstraintViolationException) ex;
            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();
            violations.forEach((item)-> {
                String key = item.getPropertyPath().toString();
                attr.addFlashAttribute(key.substring(key.lastIndexOf(".")+1),item.getMessage());
            });
        }else if(ex instanceof ValidationException){
            Arrays.asList(ex.getMessage().split(";")).forEach((item)->{
                String[] message = item.split(":");
                String msg = message[1].indexOf("FormatException")>0?"数据输入不合法":message[1];
                attr.addFlashAttribute(message[0],msg);
            });
        }else{
            System.out.println("exception");
        }
        return "redirect:"+request.getRequestURI();
    }

    /**
     * 重复数据异常处理
     * @param attr
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    public String sqlHandle(RedirectAttributes attr,HttpServletRequest request, Exception ex) {
        if(ex instanceof DuplicateKeyException){
            attr.addFlashAttribute("msg","您输入的数据已存在");
        }
        return "redirect:"+request.getRequestURI();
    }

    /**
     * 数据类型不匹配异常处理
     * @param attr
     * @param request
     * @param ex
     * @return
     */
    @ExceptionHandler(BindException.class)
    public String bindHandle(RedirectAttributes attr,HttpServletRequest request, Exception ex) {
        if(ex instanceof BindException){
            attr.addFlashAttribute("msg","数据输入不合法");
        }
        return "redirect:"+request.getRequestURI();
    }
    @ExceptionHandler(TypeMismatchException.class)
    public String methodBindHandle(RedirectAttributes attr,HttpServletRequest request, Exception ex) {
        if(ex instanceof MethodArgumentTypeMismatchException){
            attr.addFlashAttribute("msg","数据输入不合法");
        }
        return "redirect:"+request.getRequestURI();
    }

    /**
     * 授权异常处理
     * @param request
     * @param model
     * @param ex
     * @return
     */
    @ExceptionHandler(AuthorizationException.class)
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    public String authorizationHandle(HttpServletRequest request,Model model, Exception ex) {
        if(ex instanceof AuthorizationException){
            //添加越界操作登录日志
            UserFind u = (UserFind) SecurityUtils.getSubject().getPrincipal();
            if (u != null) {
                String roleName = roleService.findRole(u.getRoleId()).getRoleName();
                String logName = "loginUser:"+u.getUserName()+"=>roleName:"+roleName+"=>exception:未授权越界操作!!!";
                String addrIp = request.getRemoteAddr();
                syslogService.addSyslog(new SyslogParam(logName,addrIp,new Date()));
            }
        }
        model.addAttribute("status",401);
        return "/error";
    }

}
